package cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.domain.model;

import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.common.ApplicationContext;
import cn.caplike.demo.rabbitmq.springboot.idempotence_reliability.port.adapter.persistence.mybatis.MessageDeliveryLogRepository;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Objects;
import java.util.Optional;

/**
 * Description: 消息投递记录实体
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2020-09-01 17:22
 */
@Data
@NoArgsConstructor
public class MessageDeliveryLog {

    public static final String FIELD_MESSAGE_ID = "MESSAGE_ID";

    public static final String FIELD_MESSAGE = "MESSAGE";

    public static final String FIELD_EXCHANGE = "EXCHANGE";

    public static final String FIELD_ROUTING_KEY = "ROUTING_KEY";

    public static final String FIELD_STATUS = "STATUS";

    public static final String FIELD_RETRY_COUNT = "RETRY_COUNT";

    // -----------------------------------------------------------------------------------------------------------------
    private final MessageDeliveryLogRepository repository = ApplicationContext.getBean(MessageDeliveryLogRepository.class);
    /**
     * 消息唯一标识
     */
    private String messageId;
    /**
     * 消息体 (JSON)
     */
    private String message;
    /**
     * 交换机
     */
    private String exchange;
    /**
     * 路由键
     */
    private String routingKey;
    /**
     * 消息投递状态
     */
    private int status;

    // -----------------------------------------------------------------------------------------------------------------
    /**
     * 重试次数
     */
    private int retryCount;

    /**
     * Description: 判断消息是否已经消费
     *
     * @return boolean 成功与否
     * @author LiKe
     * @date 2020-09-02 15:38:24
     */
    public boolean hasConsumed() {
        final MessageDeliveryLog messageDeliveryLog = repository.get(this.getMessageId());

        if (Objects.nonNull(messageDeliveryLog) && messageDeliveryLog.getStatus() == Status.CONSUMED_SUCCESS) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    /**
     * Description: 更新重发状态
     *
     * @return int 更新条数
     * @author LiKe
     * @date 2020-09-03 11:01:16
     */
    public int resend() {
        final MessageDeliveryLog messageDeliveryLog =
                Optional.ofNullable(repository.get(this.getMessageId()))
                        .orElseThrow(() -> new RuntimeException(String.format("Producer :: 无此记录 (messageId: %s)", this.getMessageId())));
        messageDeliveryLog.setStatus(Status.DELIVERING);
        messageDeliveryLog.setRetryCount(messageDeliveryLog.getRetryCount() + 1);
        return repository.update(messageDeliveryLog, MessageDeliveryLog.FIELD_STATUS, MessageDeliveryLog.FIELD_RETRY_COUNT);
    }

    // -----------------------------------------------------------------------------------------------------------------

    /**
     * Description: 消息状态定义
     *
     * @author LiKe
     * @date 2020-09-02 15:33:15
     */
    public interface Status {

        // 消息投递中
        int DELIVERING = 0;

        // 投递成功
        int DELIVER_SUCCESS = 1;

        // 投递失败
        int DELIVER_FAIL = 2;

        // 已消费
        int CONSUMED_SUCCESS = 3;

    }
}
